package com.weixin.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.cookie.CookieSpecFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import com.weixin.beaninfo.AccessToken;
/**
 * 此工具类为获取AccessToken的工具类
 * 分为两种方式：
 * 				get: 得到url地址返回的数据。
 * 				post:  能将数据传输过去，并且得到返回值
 * 
 * 学习：代理类defaultHttpClient-->CloseableHttpClient
 * 							HttpResponse-->CloseableHttpResponse
 * 
 * 这些个方法用于获取某个地址返回的数据。
 * 
 * 注意事项：
 * access_token是公众号的全局唯一接口调用凭据，公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。
 * access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时，需定时刷新，
 * 		重复获取将导致上次获取的access_token失效。
 */


/**
 * 每个AccessToken有效时间只有2个小时，每天只能获取2000次。
 */
import net.sf.json.JSONObject;
/**
 * 本工具类用于获取AccessToken
 * @author 海松
 *
 */
public class AccessTokenUtils {
	private static String AppSecret="e721cdd796497cf4b0d9d8ddf38ff965";//应用密匙
	private static String AppID="wxbc0b026133fb26c9" ;//应用ID

	/**
	 * 获取存储在本地的AccessToken
	 * @param path 保存到本地的AccessToken的文件路径
	 * @return
	 */
	public static AccessToken getAccessToken(String path){
		AccessToken access_token=null;
		File file=new File(path);
		if(!file.exists()){
			return null;
		}
		try{
			//如果此文件存在,读取其中的数据
			ObjectInputStream in=new ObjectInputStream(new FileInputStream(file));
			if((access_token=(AccessToken)in.readObject())==null)
				return null;
		}catch(Exception e){
			System.out.println(e);
		}
		return access_token;
	}
	/**
	 * 将获取到的AccessToken保存至本地中
	 * @param path 保存到本地的AccessToken的文件路径
	 * @return
	 */
	public static boolean ifGetJson(String url,String path){
		File file=new File(path,"accessToken.ini");
		try {
			//如果此文件不存在
			if(!file.exists()){
				file.createNewFile();
				//写入本地文件
				write(url,file);
			}
			//如果文件存在
			if(file.exists()){
				//如果此文件存在,读取其中的数据
				ObjectInputStream in=new ObjectInputStream(new FileInputStream(file));
				AccessToken access_token=null;
				if((access_token=(AccessToken)in.readObject())==null)
					return false;
				SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");//设置日期格式
				long nowDate=Long.valueOf(df.format(new Date()));//当前时间
				long oldDate=Long.valueOf(access_token.getDate());//上一次获取accesstoken的时间
				long Expire_in=access_token.getExpire_in();//有效时间
				//如果时间间隔超过规定的有效时间Expire_in，则重新获取。只要超过了    有效时间-5分钟  则重新获取。
				if((nowDate-oldDate)>=(Expire_in-300)){
					//删除文件
					file.delete();
					//重新创建
					File file2=new File(path,"accessToken.ini");
					file2.createNewFile();
					write(url,file2);
					//关闭流
					in.close();
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		} 
		return true;
	}
	/**
	 * 通过get获取AccessToken，通过get是获取数据，无法传输数据到url上
	 * @param url
	 * @return
	 */
	public static JSONObject doGetStr(String url){
		CloseableHttpClient  client=HttpClientBuilder.create().build();
		HttpGet get=new HttpGet(url);
		JSONObject jsondata=null;
		try {
			CloseableHttpResponse response=client.execute(get);
			HttpEntity entity=response.getEntity();
			if(entity!=null){
				String result=EntityUtils.toString(entity, "UTF-8");
				jsondata=JSONObject.fromObject(result);
			}
			return jsondata;
		} catch (Exception e) {
			e.printStackTrace();
		} 
		return null;
	}
	/**
	 * 通过get获取AccessToken，通过get是获取数据，无法传输数据到url上
	 * @param url
	 * @return
	 */
	public String doGetHtml(String url){
		CloseableHttpClient  client=HttpClientBuilder.create().build();
		HttpGet get=new HttpGet(url);
		String result=null;
		try {
			CloseableHttpResponse response=client.execute(get);
			HttpEntity entity=response.getEntity();
			if(entity!=null){
				result=EntityUtils.toString(entity, "UTF-8");
			}
			return result;
		} catch (Exception e) {
			e.printStackTrace();
		} 
		return null;
	}
	/**
	 * 通过post方式获取传送数据，post获取数据，也可以传输数据到url上
	 * @return
	 */
	public static JSONObject doPostStr(String url, String outStr){
		CloseableHttpClient  client=HttpClientBuilder.create().build();
//		System.out.println("asdasda");
		HttpPost httpPost = new HttpPost(url);
		JSONObject jsondata=null;
		try {
			httpPost.setEntity(new StringEntity(outStr,"UTF-8"));
			CloseableHttpResponse response=client.execute(httpPost);
			String result=EntityUtils.toString(response.getEntity(), "UTF-8");
			jsondata=JSONObject.fromObject(result);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return jsondata;
	}
	/**
	 * 将信息写入到本地文件
	 * @param url  获取AccessToken网址
	 * @param file 本地文件
	 * @return
	 */
	private static boolean write(String url,File file){
		AccessToken access_token=new AccessToken();
		try{
			ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream(file));
			//获取首次的AccessToken JSON数据
			url=url.replaceFirst("APPID", AppID);//交换appID
			url=url.replaceFirst("APPSECRET", AppSecret);//交换密匙
			JSONObject jsondata=doGetStr(url);
			access_token.setAccessToken((String)jsondata.get("access_token"));
//			System.out.println("access_token"+jsondata.get("access_token"));测试
			access_token.setExpire_in(Integer.valueOf(String.valueOf(jsondata.get("expires_in"))));//
			//再对firJson添加获取日期
			SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");//设置日期格式
			access_token.setDate(df.format(new Date()));
			if(access_token!=null){
				//读取获取到的AccessToken JSON数据对象，将其写入到文件中
				out.writeObject(access_token);
			}
			out.flush();
			out.close();
		}catch(Exception e){
			System.out.println("write方法写入文件出错："+e);
			return false;
		}
		return true;
	}
}
